#include "Kernel.h"
#include "Utils/Spinlock.h"
#include "Scheduler/Scheduler.h"
#include "Hal/IHardware.h"
#include "Hal/Atomic.h"


CSpinlock::CSpinlock()
{
	fState = Ready;
	fThread = NULL;
}


CSpinlock::~CSpinlock()
{
	sHardware->Lock();

	Atomic_Set( &fState, Disposed );
	fThread = NULL;

    Hardware->Unlock();
}


void CSpinlock::Lock( void )
{
	ASSERT_SZ( Atomic_Get( &fState ) != Disposed, "Attempted to lock a disposed spinlock." );

	while( Atomic_TestAndSet( &fState, Ready, Locked ) != Ready )
		; // do nothing

	Hardware->Lock();
	fThread = Scheduler::CurrentThread;
}


void CSpinlock::Unlock( void )
{
	ASSERT_SZ( Atomic_Get( &fState ) != Disposed, "Attempted to unlock a disposed spinlock." );
	ASSERT_SZ( Atomic_Get( &fState ) == Locked, "Attempted to unlock a unlocked spinlock." );

	Atomic_Set( &fState, Locked );
	fThread = NULL;

	Hardware->Unlock();
}


bool CSpinlock::IsLocked( void )
{
	return Atomic_Get( &fState ) == Locked;
}
